#ifndef ODN_GAMEWORLD_H
#define ODN_GAMEWORLD_H

#include <cassert>
#include <ogre\Ogre.h>

#include "ODN_DLLAccess.h"
#include "ODN_Containers.h"
#include "ODN_String.h"
#include "ODN_BaseEntity.h"

//TODO: Make sure removal of # before typeString doesn't stuff things up
#define REGISTER_ENTITY_CLASS(typeString, className) ouden::CGameMgr::getInstance()->getGameWorld()->registerEntity(typeString, &className::create);

namespace ouden {

class CBaseEntity;
class ODN_DLLACCESS CModelEntity;

class ODN_DLLACCESS CGameWorld
{
	
	private:
		
		//Typedef "Ptr2EntCreateFunc" as function pointer to an entity's static create function
		typedef CBaseEntity* (*Ptr2EntFactory)(String sName);
	
	public:
		CGameWorld();
		virtual ~CGameWorld();
		
		//Updates all world entities
		void update();
		
		//Creates a new entity by type identifying string and returns a pointer to it
		CBaseEntity* createEntity(String sType, String sName="");
		
		//Registers a type identifying string to an entity factory for creating
		// entities by name
		bool registerEntity(String sType, Ptr2EntFactory fpEntFactory);
		
		//Returns a pointer to an entity referenced by name
		CBaseEntity* findEntity(String sName);
		
		//Removes an entity from the game world and destroys it
		bool destroyEntity(CBaseEntity* &pEntity);
		
		void addEntityToCategory(CBaseEntity* pEntity, String sCategory)
			{ m_pCategoryMap[sCategory].push_back(pEntity); }
		
		bool isEntityInCategory(CBaseEntity* pEntity, String sCategory)
			{ return ( find(m_pCategoryMap[sCategory].begin(), m_pCategoryMap[sCategory].end(), pEntity) != m_pCategoryMap[sCategory].end() ); }
		
	protected:
	private:
		
		//Array of entities in the game world
		Array<CBaseEntity*> m_pEntities;
		
		Map<String, Ptr2EntFactory> 	m_fpEntityFactoryMap; 	//Map of entity names to their factory pointers
		
		//Useful entity maps
		typedef Array<CBaseEntity*> tEntityCategory;
		Map<String, tEntityCategory> m_pCategoryMap; 	//Map of entity categories by name
		Map<String, CBaseEntity*> 	m_pEntityMap; 	//Map of entities by name
		
};

} //namespace ouden

#endif // ODN_GAMEWORLD_H
